/*
 * @Date: 2025-09-19 18:04:30
 * @LastEditors: lixu lixu@puchigames.com
 * @LastEditTime: 2025-09-26 09:39:15
 * @FilePath: /db/cache.go
 * @Description:
 */
package ixOrm

import (
	"encoding/json"
	"fmt"
	"reflect"
	"strings"
	"sync"
	"time"

	ixRedis "gitee.com/ixgo/redis"
)

// CacheInterface 缓存接口
type CacheInterface interface {
	Get(key string, dest interface{}) (bool, error)
	Set(key string, value interface{}, ttl time.Duration) error
	Del(keys ...string) error
	DelPattern(pattern string) error
	Clear() error
}

// RedisCache Redis缓存实现
type RedisCache struct {
	client *ixRedis.Client
	prefix string
	ttl    time.Duration
}

// NewRedisCache 创建Redis缓存
func NewRedisCache(client *ixRedis.Client, prefix string, ttl time.Duration) *RedisCache {
	if prefix == "" {
		prefix = "ixorm:"
	}
	return &RedisCache{
		client: client,
		prefix: prefix,
		ttl:    ttl,
	}
}

// Get 获取缓存
func (rc *RedisCache) Get(key string, dest interface{}) (bool, error) {
	return rc.client.Get(rc.getKey(key), dest)
}

// Set 设置缓存
func (rc *RedisCache) Set(key string, value interface{}, ttl time.Duration) error {
	if ttl == 0 {
		ttl = rc.ttl
	}
	return rc.client.SetWithExpire(rc.getKey(key), value, ttl)
}

// Del 删除缓存
func (rc *RedisCache) Del(keys ...string) error {
	fullKeys := make([]string, len(keys))
	for i, key := range keys {
		fullKeys[i] = rc.getKey(key)
	}
	_, err := rc.client.Del(fullKeys...)
	return err
}

// DelPattern 根据模式删除缓存
func (rc *RedisCache) DelPattern(pattern string) error {
	// 直接使用ixRedis的Keys和Del方法，避免CacheDecorator的前缀问题
	fullPattern := rc.prefix + pattern
	keys, err := rc.client.Keys(fullPattern)
	if err != nil {
		return err
	}

	if len(keys) > 0 {
		_, err = rc.client.Del(keys...)
	}
	return err
}

// Clear 清空所有缓存
func (rc *RedisCache) Clear() error {
	pattern := rc.prefix + "*"
	keys, err := rc.client.Keys(pattern)
	if err != nil {
		return err
	}

	if len(keys) > 0 {
		_, err = rc.client.Del(keys...)
	}
	return err
}

// getKey 获取完整键名
func (rc *RedisCache) getKey(key string) string {
	// 如果键已经包含前缀，直接返回
	if strings.HasPrefix(key, rc.prefix) {
		return key
	}
	// 否则添加前缀
	return rc.prefix + key
}

// NullCache 空缓存实现（当不使用缓存时）
type NullCache struct{}

// NewNullCache 创建空缓存
func NewNullCache() *NullCache {
	return &NullCache{}
}

// Get 空实现
func (nc *NullCache) Get(key string, dest interface{}) (bool, error) {
	return false, nil
}

// Set 空实现
func (nc *NullCache) Set(key string, value interface{}, ttl time.Duration) error {
	return nil
}

// Del 空实现
func (nc *NullCache) Del(keys ...string) error {
	return nil
}

// DelPattern 空实现
func (nc *NullCache) DelPattern(pattern string) error {
	return nil
}

// Clear 空实现
func (nc *NullCache) Clear() error {
	return nil
}

// CacheItem 缓存项
type CacheItem struct {
	Value     interface{}
	ExpiredAt time.Time
}

// IsExpired 检查是否过期
func (item *CacheItem) IsExpired() bool {
	return time.Now().After(item.ExpiredAt)
}

// MemoryCache 内存缓存实现
type MemoryCache struct {
	data       map[string]*CacheItem
	mutex      sync.RWMutex
	prefix     string
	defaultTTL time.Duration
	stopChan   chan struct{} // 用于停止清理goroutine
	debugMode  bool          // 调试模式

	// 性能统计
	hitCount  int64 // 命中次数
	missCount int64 // 未命中次数
}

// NewMemoryCache 创建内存缓存
func NewMemoryCache(prefix string, defaultTTL time.Duration) *MemoryCache {
	if prefix == "" {
		prefix = "ixorm:memory:"
	}
	if defaultTTL == 0 {
		defaultTTL = time.Minute * 5
	}

	cache := &MemoryCache{
		data:       make(map[string]*CacheItem),
		prefix:     prefix,
		defaultTTL: defaultTTL,
		stopChan:   make(chan struct{}),
		debugMode:  false, // 默认关闭调试模式
	}

	// 启动清理过期数据的goroutine
	go cache.startCleanup()

	return cache
}

// Get 获取缓存
func (mc *MemoryCache) Get(key string, dest interface{}) (bool, error) {
	if mc == nil {
		return false, fmt.Errorf("内存缓存未初始化")
	}
	if key == "" {
		return false, fmt.Errorf("缓存键不能为空")
	}

	fullKey := mc.getKey(key)

	// 使用读写锁，但避免锁升级
	mc.mutex.RLock()
	item, exists := mc.data[fullKey]
	if !exists {
		mc.mutex.RUnlock()
		mc.missCount++
		return false, nil
	}

	// 检查是否过期（在读锁下检查）
	if item.IsExpired() {
		mc.mutex.RUnlock()
		// 过期项延迟删除，避免在读锁下删除
		mc.missCount++
		return false, nil
	}

	// 复制值（在读锁下进行，确保数据一致性）
	var value interface{}
	if item.Value != nil {
		// 深拷贝值，避免并发修改
		value = item.Value
	}
	// 注意：即使item.Value为nil，我们也继续处理，因为nil也是一个有效值
	mc.mutex.RUnlock()

	// 尝试将值复制到dest - 使用与Redis缓存相同的方式
	if dest != nil {
		if mc.debugMode {
			fmt.Printf("[ixOrm-DEBUG] 内存缓存Get - 缓存值类型: %v, 缓存值: %+v\n",
				reflect.TypeOf(value), value)
		}

		if value == nil {
			if mc.debugMode {
				fmt.Printf("[ixOrm-DEBUG] 内存缓存Get - 缓存值为nil\n")
			}
			return true, nil
		}

		// 使用JSON序列化/反序列化，与Redis缓存保持一致
		jsonData, err := json.Marshal(value)
		if err != nil {
			if mc.debugMode {
				fmt.Printf("[ixOrm-DEBUG] 内存缓存Get - JSON序列化失败: %v\n", err)
			}
			return false, fmt.Errorf("JSON序列化失败: %v", err)
		}

		if mc.debugMode {
			fmt.Printf("[ixOrm-DEBUG] 内存缓存Get - JSON数据: %s\n", string(jsonData))
		}

		err = json.Unmarshal(jsonData, dest)
		if err != nil {
			if mc.debugMode {
				fmt.Printf("[ixOrm-DEBUG] 内存缓存Get - JSON反序列化失败: %v\n", err)
			}
			return false, fmt.Errorf("JSON反序列化失败: %v", err)
		}

		if mc.debugMode {
			fmt.Printf("[ixOrm-DEBUG] 内存缓存Get - JSON反序列化成功\n")
		}
	}

	mc.hitCount++
	return true, nil
}

// Set 设置缓存
func (mc *MemoryCache) Set(key string, value interface{}, ttl time.Duration) error {
	if mc == nil {
		return fmt.Errorf("内存缓存未初始化")
	}
	if key == "" {
		return fmt.Errorf("缓存键不能为空")
	}
	if value == nil {
		return fmt.Errorf("缓存值不能为nil")
	}

	if ttl == 0 {
		ttl = mc.defaultTTL
	}

	// 创建新的缓存项
	newItem := &CacheItem{
		Value:     value,
		ExpiredAt: time.Now().Add(ttl),
	}

	mc.mutex.Lock()
	defer mc.mutex.Unlock()

	fullKey := mc.getKey(key)
	mc.data[fullKey] = newItem

	return nil
}

// Del 删除缓存
func (mc *MemoryCache) Del(keys ...string) error {
	mc.mutex.Lock()
	defer mc.mutex.Unlock()

	for _, key := range keys {
		fullKey := mc.getKey(key)
		delete(mc.data, fullKey)
	}

	return nil
}

// DelPattern 根据模式删除缓存
func (mc *MemoryCache) DelPattern(pattern string) error {
	mc.mutex.Lock()
	defer mc.mutex.Unlock()

	fullPattern := mc.prefix + pattern
	keysToDelete := make([]string, 0)

	for key := range mc.data {
		if matchPattern(key, fullPattern) {
			keysToDelete = append(keysToDelete, key)
		}
	}

	for _, key := range keysToDelete {
		delete(mc.data, key)
	}

	return nil
}

// Clear 清空所有缓存
func (mc *MemoryCache) Clear() error {
	mc.mutex.Lock()
	defer mc.mutex.Unlock()

	// 只清空带前缀的缓存
	keysToDelete := make([]string, 0)
	for key := range mc.data {
		if len(key) >= len(mc.prefix) && key[:len(mc.prefix)] == mc.prefix {
			keysToDelete = append(keysToDelete, key)
		}
	}

	for _, key := range keysToDelete {
		delete(mc.data, key)
	}

	return nil
}

// Close 关闭内存缓存，停止清理goroutine
func (mc *MemoryCache) Close() error {
	close(mc.stopChan)
	return nil
}

// SetDebugMode 设置调试模式
func (mc *MemoryCache) SetDebugMode(debug bool) {
	if mc == nil {
		return
	}
	mc.mutex.Lock()
	mc.debugMode = debug
	mc.mutex.Unlock()
}

// GetStats 获取缓存统计信息
func (mc *MemoryCache) GetStats() map[string]interface{} {
	if mc == nil {
		return nil
	}

	mc.mutex.RLock()
	defer mc.mutex.RUnlock()

	total := mc.hitCount + mc.missCount
	hitRate := float64(0)
	if total > 0 {
		hitRate = float64(mc.hitCount) / float64(total) * 100
	}

	return map[string]interface{}{
		"hit_count":  mc.hitCount,
		"miss_count": mc.missCount,
		"total":      total,
		"hit_rate":   hitRate,
		"size":       len(mc.data),
		"debug_mode": mc.debugMode,
	}
}

// getKey 获取完整键名
func (mc *MemoryCache) getKey(key string) string {
	// 如果键已经包含前缀，直接返回
	if strings.HasPrefix(key, mc.prefix) {
		return key
	}
	// 否则添加前缀
	return mc.prefix + key
}

// startCleanup 启动清理过期数据的goroutine
func (mc *MemoryCache) startCleanup() {
	ticker := time.NewTicker(time.Minute) // 每分钟清理一次
	defer ticker.Stop()

	for {
		select {
		case <-ticker.C:
			mc.cleanup()
		case <-mc.stopChan:
			return // 收到停止信号，退出goroutine
		}
	}
}

// cleanup 清理过期数据
func (mc *MemoryCache) cleanup() {
	mc.mutex.Lock()
	defer mc.mutex.Unlock()

	now := time.Now()
	keysToDelete := make([]string, 0, len(mc.data)/4) // 预估容量

	for key, item := range mc.data {
		if now.After(item.ExpiredAt) {
			keysToDelete = append(keysToDelete, key)
		}
	}

	// 批量删除过期项
	for _, key := range keysToDelete {
		delete(mc.data, key)
	}

	// 记录清理信息
	if len(keysToDelete) > 0 {
		fmt.Printf("[ixOrm] 内存缓存清理: 删除了 %d 个过期项\n", len(keysToDelete))
	}
}

// matchPattern 简单的模式匹配（支持*通配符）
func matchPattern(str, pattern string) bool {
	if pattern == "*" {
		return true
	}

	// 简单的通配符匹配实现
	i, j := 0, 0
	for i < len(str) && j < len(pattern) {
		if pattern[j] == '*' {
			// 跳过连续的*
			for j < len(pattern) && pattern[j] == '*' {
				j++
			}
			if j == len(pattern) {
				return true // 模式以*结尾，匹配剩余所有字符
			}
			// 查找下一个匹配点
			for i < len(str) {
				if matchPattern(str[i:], pattern[j:]) {
					return true
				}
				i++
			}
			return false
		} else if str[i] == pattern[j] {
			i++
			j++
		} else {
			return false
		}
	}

	return i == len(str) && j == len(pattern)
}

// tryJSONConversion 尝试通过JSON序列化/反序列化进行类型转换
func (mc *MemoryCache) tryJSONConversion(sourceValue reflect.Value, destElem reflect.Value) bool {
	// 检查源值是否有效
	if !sourceValue.IsValid() || sourceValue.IsNil() {
		if mc.debugMode {
			fmt.Printf("[ixOrm-DEBUG] 源值无效或为nil\n")
		}
		return false
	}

	// 检查目标值是否可设置
	if !destElem.CanSet() {
		if mc.debugMode {
			fmt.Printf("[ixOrm-DEBUG] 目标值不可设置\n")
		}
		return false
	}

	// 将源值序列化为JSON
	jsonData, err := json.Marshal(sourceValue.Interface())
	if err != nil {
		if mc.debugMode {
			fmt.Printf("[ixOrm-DEBUG] JSON序列化失败: %v\n", err)
		}
		return false
	}

	if mc.debugMode {
		fmt.Printf("[ixOrm-DEBUG] JSON数据: %s\n", string(jsonData))
	}

	// 将JSON反序列化到目标值
	err = json.Unmarshal(jsonData, destElem.Addr().Interface())
	if err != nil {
		if mc.debugMode {
			fmt.Printf("[ixOrm-DEBUG] JSON反序列化失败: %v\n", err)
		}
		return false
	}

	return true
}
